﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;

namespace BenevolentSunData
{

    public class HueCell : Cell
    {

        private String colorName;
        public String ColorName
        {
            get
            {
                return colorName;
            }
        }

        public override string Name
        {
            get { 
                if (hasWalls == false)
                    return colorName + " Filter";
                else
                {
                    return "Walled " + colorName + " Filter";
                }
            }
        }

        public override string Note
        {
            get
            {
                if (isOn == false)
                {
                    return "Hit with a sufficient color beam of light to change the beam color to " + colorName;
                }
                return "Colors the beam " + colorName;
            }
        }

        #region State
        private Color hue = new Color(255, 0, 0);//Color.Lime; // Alpha, Red, Green, Blue
        public Color Hue
        {
            get { return hue; }
            set { 
                hue = value;
                if (hue.Equals(Color.Red))
                    colorName = "Red";
                else if (hue.Equals(Color.Lime))
                    colorName = "Green";
                else if (hue.Equals(Color.Blue))
                    colorName = "Blue";
                else if (hue.Equals(Color.Fuchsia))
                    colorName = "Pink";
                else if (hue.Equals(Color.Yellow))
                    colorName = "Yellow";
                else if (hue.Equals(Color.Aqua))
                    colorName = "Aqua";
                else if (hue.Equals(Color.White))
                    colorName = "White";
                else
                    throw (new Exception("Unknown filter color: " + hue));
            }
        }

        private bool hasWalls = false;
        [ContentSerializer(Optional=true)]
        public bool HasWalls
        {
            get { return hasWalls; }
            set { hasWalls = value; }
        }

        private Orientation orientation = Orientation.NorthSouth;
        [ContentSerializer(Optional = true)]
        public Orientation Orientation
        {
            get { return orientation; }
            set 
            {     
                orientation = value;
                Rotation = 0f;
                if (orientation == Orientation.EastWest)
                    Rotation = (float)Math.PI / 2f;
            }
        }
        #endregion


        #region Graphics
        Model wallsModel;

        Material filterMaterial, wallsMaterial;

        Matrix[] boneTransforms;
        #endregion


        #region Drawing
        public override void Draw(Vector3 position)
        {
            foreach (ModelMesh mesh in wallsModel.Meshes)
            {
                Material material;
                if (mesh.ParentBone.Parent.Name == "Filter") {
                    material = filterMaterial;
                } else {
                    if (hasWalls == false)
                        continue;
                    material = wallsMaterial;
                }

                Matrix world =
                    boneTransforms[mesh.ParentBone.Index] *
                    Matrix.CreateFromYawPitchRoll(Rotation, 0f, 0f) *
                    Matrix.CreateTranslation(position);
                material.DrawMesh(mesh, world, Map.PointLights, Map.BeamLights);
            }
        }




       #endregion


        #region Initialization
        public HueCell() {}

        public override void LoadContent(ContentManager Content, Map map)
        {
            base.LoadContent(Content, map);

            wallsModel = Content.Load<Model>("Models/Hue");
            boneTransforms = new Matrix[wallsModel.Bones.Count];
            wallsModel.CopyAbsoluteBoneTransformsTo(boneTransforms);

            wallsMaterial = map.Skin.GetMaterial("Hue Walls");
            filterMaterial = map.Skin.GetMaterial("Hue Filter");
        }
        #endregion


        #region Beams
        public override void Clear()
        {
            filterMaterial.EmissiveColor = Color.Black; // hue to 0.7?/
            filterMaterial.Alpha = 0.3f;
            filterMaterial.DiffuseColor = hue;
            isOn = false;
            base.Clear();
        }

        bool isOn = false;

        public override List<Direction> AddInput(Beam beam, Direction direction)
        {
            List<Direction> output = new List<Direction>();
            MergeBeam(beam, direction);

            if ((!hasWalls || DirectionUtils.IsInOrientation(orientation, direction)) && CanColorize(beam))
            {
                isOn = true;

                filterMaterial.EmissiveColor = hue; // hue to 0.7?/
                filterMaterial.Alpha = 0.6f;

                Direction through = DirectionUtils.Invert(direction);

                if (MergeBeam(Colorize(beam), through))
                    output.Add(through);
            }

            return output;
        }

        private bool CanColorize(Beam beam)
        {
            if (
                beam.Color.R >= hue.R && 
                beam.Color.G >= hue.G && 
                beam.Color.B >= hue.B &&
                beam.Color.A >= hue.A)
            {
                return true;
            }
            return false;
        }

        private Beam Colorize(Beam beam)
        {
            Beam coloredBeam = beam.Clone() as Beam;
            coloredBeam.Color = Hue;
            return coloredBeam;
        }
        #endregion


        #region ICloneable
        public override object Clone()
        {
            HueCell cell = new HueCell();
            cell.Coords = new Point(Coords.X, Coords.Y);
            cell.Hue = new Color(hue.R, hue.G, hue.B, hue.A);
            cell.filterMaterial = filterMaterial.Clone();
            cell.wallsMaterial = wallsMaterial.Clone();
            cell.wallsModel = wallsModel;
            cell.Orientation = orientation;
            cell.boneTransforms = boneTransforms;
            cell.floorBoneTransforms = floorBoneTransforms;
            cell.floorModel = floorModel;
            cell.floorMaterial = floorMaterial.Clone();
            return cell;
        }
        #endregion

    }
}

